﻿<?php
/**************************************
     File Name: DBTreeManager.php
     Begin:  Sunday, April, 12, 2009, 11:36 AM
     Author: Ozan Koroglu
 			 Ahmet Oguz Mermerkaya 	
     Email:  koroglu.ozan@gmail.com
     		 ahmetmermerkaya@hotmail.com
 ***************************************/ 
 
 require_once('ITreeManager.php');

 class DBTreeManager implements ITreeManager
 {
 	private $db;
	
    public function __construct($dbc){
    	$this->db = $dbc;
    } 
	
 	public function insertElement($lo_name, $parent_id, $program_id)
	{
		
		$sql_getparent="select lo_id from mdl_learning_outcome  where id='". $parent_id ." '";
			$parent_lo="";
			$result = $this->db->query($sql_getparent);
			if($result !== false)
			{
				while ($id = $this->db->fetchObject($result))
				{
					$parent_lo =$id->lo_id;
				}
			}
			
			
		$sql="SELECT max(lo_id) as abc FROM mdl_learning_outcome WHERE parent_lo_id='".$parent_lo."' and program_id='".$program_id."'";
			$max_id="";
			$result = $this->db->query($sql);
			if($result !== false)
			{
				while ($id = $this->db->fetchObject($result))
				{
					$max_id =$id->abc;
				}
			}	
			$last=1;
			$level=count(explode('.', $parent_lo))+$last;
			//================================ tao lo id=====================================
			$lo_id="";
			$temp="";
			if($max_id=='')
			{
				//kiem tra node la thi ko tra id lai
				//lay max level cua lo
				$sql2="SELECT max(lo_level) as maxlevel FROM mdl_learning_outcome WHERE program_id='".$program_id."'";
				$max_level="";
				$result = $this->db->query($sql2);
				if($result !== false)
				{
					while ($id = $this->db->fetchObject($result))
					{
						$max_level =$id->maxlevel;
					}
				}	
				
				if($level<$max_level)
				{
					$lo_id= $parent_lo.'.1';
				}
				else		
				{
					$lo_id= '';
				}
			}
			else
			{
				//khuc nṠcat chuoi de l?y ph?n d?u c?a s? c?n tang, v𩁵 maxid l࠱.2.3 th젿 day c?t l?y chuoi 1.2. d? lⴠgh갠vᯠsau khi tang s? 3 thᯨ so 4
				$cons=1;  
				$pre_id= substr($max_id, 0, $this->lastIndexOf($max_id,'.'));
				$last_id= $this->parseInt(substr($max_id, $this->lastIndexOf($max_id, '.')))+$cons;
				$lo_id= $pre_id.'.'.$last_id;
			}
			//================================ ket thuc tao lo id=====================================
			$sql_insert = "insert into ". TREE_TABLE_PREFIX ."_learning_outcome ( `lo_id`, `lo_level`, `lo_name`, `parent_lo_id`, `program_id`, `status`) values('".$lo_id."', '".$level."', '".$lo_name."', '".$parent_lo."', ".$program_id.", 1)";
			
			$out = FAILED;
			if ($this->db->query($sql_insert) == true) {
					$out = '({ "loid":"'.$lo_id.'", "loname":"'.$lo_name.'"})';
			}
			
			return $out; 		
 	}
	public function parseInt($string) {
		//  return intval($string);
		if(preg_match('/(\d+)/', $string, $array)) {
		return $array[1];
		} else {
		return 0;
		}
	}
	//string  = 1.1.1 $item ='.'
 	public function lastIndexOf($string,$item){  
		$index=strpos(strrev($string),strrev($item));  
		if ($index){  
			$index=strlen($string)-strlen($item)-$index;  
			return $index;  
		}  
			else  
			return -1;  
	}
 	//=======================================================================================
 	public function getElementList($ownerEl, $pageName, $programid)
	{
		
		if ($ownerEl == null) {
			$ownerEl = '0';
		}
		//lay max level cua lo
				$sql2="SELECT max(lo_level) as maxlevel FROM mdl_learning_outcome WHERE program_id='".$programid."'";
				$max_level="";
				$result = $this->db->query($sql2);
				if($result !== false)
				{
					while ($id = $this->db->fetchObject($result))
					{
						$max_level =$id->maxlevel;
					}
				}	
				
		$sql = "SELECT 
        					*
        				FROM mdl_learning_outcome
		      			WHERE
		      				parent_lo_id = '".$ownerEl."'  and program_id= '".$programid."'
		      			ORDER BY
		      				lo_id ";
						
		$str = FAILED;
        $result = $this->db->query($sql);
        if ($result !== false)
        {
        	$str = NULL;
            while ($row = $this->db->fetchObject($result))
            {
                $supp = NULL;
                if ($row->lo_id != '')
                {
                    $supp = "<ul class='ajax'>"
                    ."<li id='".$row->id."'>{url:".$pageName."?action=getElementList&ownerEl=".$row->lo_id."&programid=".$programid."}</li>"
                    ."</ul>";
                }
        
                $str .= "<li class='text' id='".$row->id."'>"
                ."<span maxlevel='".$max_level."' level='".$row->lo_level."' loid='".$row->lo_id."'>".$row->lo_id.'  '.$row->lo_name."</span>"
                .$supp
                ."</li>";
            }
        }
        return $str;				
						
 	
 	}
 	
 	
 	public function updateElementName($name, $loid)
	{
		$sql_getparent="select lo_id, program_id from mdl_learning_outcome  where id='". $loid ." '";
			$parent_lo="";
			$program_id="";
			$result = $this->db->query($sql_getparent);
			if($result !== false)
			{
				while ($id = $this->db->fetchObject($result))
				{
					$parent_lo =$id->lo_id;
					$program_id=$id->program_id;
				}
			}
			
		$elementId = (int) $loid;
 		$sql = sprintf('UPDATE ' 
        						. TREE_TABLE_PREFIX.'_learning_outcome 
							SET 
								lo_name = \'%s\'
					    	WHERE 
					    		id = %d ',
        					$name, $elementId);
		$out = FAILED;					
		if ($this->db->query($sql) == true) {
				$out = '({"elementName":"'.$name.'", "elementId":"'.$elementId.'", "loid":"'.$parent_lo.'", "programid":"'.$program_id.'"})';
		}
		
		return $out;
 	}

	public function xoa_lo($loid_canxoa, $program_id)
	{
		////xóa  lo trước sau do se cap nhat lo_id của những thằng lo dưới nó
			///ví dụ khi xóa lo 1.2 thì thằng lo 1.3 sẽ được đôn lên thành 1.2
			 
			 $sqlupdate_status= "update mdl_learning_outcome set status=-2 where id=".$loid_canxoa;
					 $this->db->query($sqlupdate_status);
					 
			 $sql_duyet_lo_con = "select * from mdl_learning_outcome where parent_lo_id in ( select lo_id from mdl_learning_outcome where id='".$loid_canxoa."') and program_id='".$program_id."' ";
			 $row = NULL;
			 if ($result = $this->db->query($sql_duyet_lo_con))
			 {
				 while ($row = $this->db->fetchObject($result))
				 {
					 //kiem tra neu no node con thì duyet vao cac node con cua no
					 //cùng lúc đó chuyển trạng thái nó về -2 để sau đó mình sẽ dựa vào
					 //thuộc tính -2 này để xóa các LO đã duyệt qua
					 $sqlupdate_status= "update mdl_learning_outcome set status=-2 where id=".$row->id;
					 $this->db->query($sqlupdate_status);
					 //lo_id mà ko trống có nghĩa là thằng này ko phải node lá, nó dang có con
					 // duyêt đến node con bằng hàm đệ quy
					 if ($row->lo_id != "")
					 {
						 // recursive operation, to reach the deepest element
						 $this->xoa_lo($row->id, $program_id);
					 }
				 }
			 }
	}	
	
	
	
	public function update_loid_after_delete($loid_xoa, $loid_cha, $program_id)
	{
		//lấy số cuối của loid bị xóa, sau khi lấy dc số cuối thì tăng giảm các loid còn lại trong cùng 1 node cha cho phù hợp
		$socuoixoa=$this->parseInt(substr($loid_xoa, $this->lastIndexOf('.',$loid_xoa)));
		//duyet tat ca cac LO khác cùng cấp, nếu số cuối của các LO này lớn hơn số cuối của thằng bị xóa thì đôn nó lên
		$sql="SELECT * FROM `mdl_learning_outcome` WHERE lo_id !='".$loid_xoa."' and program_id=".$program_id." and parent_lo_id='".$loid_cha."'";
		
		$row = NULL;
		if ($result = $this->db->query($sql))
		{
			while ($row = $this->db->fetchObject($result))
			{
				$loid=$row->lo_id;
				$sodausua=substr($loid, 0, $this->lastIndexOf($loid,'.'));
				$socuoisua=$this->parseInt(substr($loid, $this->lastIndexOf($loid,'.')));
				
				if($socuoisua>$socuoixoa)
				{
					$socuoimoi=$socuoisua-1;
					if($sodausua=="")
					{
						$loid_moi=$socuoimoi;
					}
					else
					{
						$loid_moi=$sodausua.'.'.$socuoimoi;
					}
					$sql_update_lo= "update mdl_learning_outcome set lo_id='".$loid_moi."' where id=".$row->id;
					$this->db->query($sql_update_lo);
					
					//cập nhật lo id của các node con, ví dụ khi xóa node 1.1 thì 1.2 đôn lên thành 1.1
					//và các con của 1.2 sẽ đổi thành 1.1 ví dụ 1.2 đôn lên, các con 1.2.1, 1.2.2, 1.2.3 sẽ đôn lên thành 1.1.1, 1.1.2, 1.1.3
					$this->capnhat_id_node_con($loid_moi, $loid, $program_id);
						 
				}
			}
		}	
	}	
 	//public function deleteElement($elementId, $parentid, $programid)
     public function deleteElement($loid_canxoa, $program_id)
     {
		$this->xoa_lo($loid_canxoa, $program_id);
		
         // cap nhat lai lo id cho nhung thằng đứng sau thằng lo bi xoa
         $sql_duyet_lo_con = "select * from mdl_learning_outcome where id='".$loid_canxoa."' and program_id='".$program_id."' ";
		 echo '<script>alert("'.$sql_duyet_lo_con.'")</script>';
			 $row = NULL;
			 $lo_cha="";
			 $lo_id="";
			 if ($result = $this->db->query($sql_duyet_lo_con))
			 {
				 while ($row = $this->db->fetchObject($result))
				 {
					$lo_id=$row->lo_id;
					$lo_cha= substr($lo_id, 0, $this->lastIndexOf($lo_id,'.'));
					if($lo_cha=="")
					{
						$lo_cha='0';
					}
					$this->update_loid_after_delete($lo_id, $lo_cha,$program_id);
					
				 }
			}
		$sql_xoa = "delete from mdl_learning_outcome where status=-2 and program_id='".$program_id."' ";
		$this->db->query($sql_xoa);			
         return 'lo cha: '.$lo_cha.'; lo id:'.$lo_id;     
     }
 	public function capnhat_id_node_con2($loid_chamoi, $loid_chacu, $program_id)
	{
		//cap nhat node cha trước
		$sqllistchilds="select * from mdl_learning_outcome where parent_lo_id='".$loid_chacu."' and status>0 and program_id='".$program_id."' ";
		$row = NULL;
		if ($result = $this->db->query($sqllistchilds))
		{
			while ($row = $this->db->fetchObject($result))
			{
				$sql_cap_nhat_cha = "update mdl_learning_outcome set parent_lo_id='".$loid_chamoi."' where id='".$row->id."' and status>0 and program_id='".$program_id."' ";
				$this->db->query($sql_cap_nhat_cha);
			}
		}	
		//giờ tới lượt cập nhật lo_id của node con theo node cha da thay doi
		$sql_duyet_lo_con = "select * from mdl_learning_outcome where parent_lo_id='".$loid_chamoi."' and program_id='".$program_id."' ";
		$row = NULL;
		if ($result = $this->db->query($sql_duyet_lo_con))
		{
			while ($row = $this->db->fetchObject($result))
			{
				if($row->lo_id!='')
				{
					$lo_id=$row->lo_id;
					$socuoisua=$this->parseInt(substr($lo_id, $this->lastIndexOf($lo_id,'.')));
					$lo_id_moi= $loid_chamoi.'.'.$socuoisua;
					$sql_cap_nhat_con = "update mdl_learning_outcome set lo_id='".$lo_id_moi."' where id='".$row->id."'";
						$this->db->query($sql_cap_nhat_con);
					$this->capnhat_id_node_con($lo_id_moi, $lo_id,$program_id);
				}	
			}
		}
	}
 	public function changeOrder($elementId, $oldOwnerEl, $destOwnerEl, $destPosition, $programid)
	{
		//$elementId: là LO ID mà bị kéo
		//$oldOwnerEl: là node cha cũ
		//$destOwnerEl: là node cha mới
		//$destPosition: là vị trí thả vào
		//tăng vị trí thả vào 1 đơn vị, ví dụ khi kéo node 4.1 vào node 5 ở vị trí 0 (vi tri 0 là vị trí đầu tiên)
		//thì lo_id mới của 4.1 sẽ là 5.1 dong nghia voi = vị trí mới thả vào + 1	

		$destPosition++;
		//lay lo_id cua item moi keo vao
		$sql_lay_loid_cu = "select * from mdl_learning_outcome where id='".$elementId."' and program_id='".$programid."' ";
		$lo_id_cu="";
		$row = NULL;
		if ($result = $this->db->query($sql_lay_loid_cu))
		{
			while ($row = $this->db->fetchObject($result))
			{
				$lo_id_cu=$row->lo_id;
			}	
		}
		//============================
		
		//lấy lo_id của cha mới
		$sql_duyet_lo_con = "select * from mdl_learning_outcome where id='".$destOwnerEl."' and program_id='".$programid."' ";
		$lo_id_moi="";
		$lo_id_cha="";
		$row = NULL;
		if ($result = $this->db->query($sql_duyet_lo_con))
		{
			while ($row = $this->db->fetchObject($result))
			{
				$lo_id_cha=$row->lo_id;
				if($lo_id_cu!="")
				{
					$lo_id_moi=$lo_id_cha.'.'.$destPosition;
				}
			
			}	
		}
		//lấy lo_id của cha cũ
		$sql_duyet_lo_con = "select * from mdl_learning_outcome where id='".$oldOwnerEl."' and program_id='".$programid."' ";
		$lo_id_cha_cu="";
		$row = NULL;
		if ($result = $this->db->query($sql_duyet_lo_con))
		{
			while ($row = $this->db->fetchObject($result))
			{
				$lo_id_cha_cu=$row->lo_id;
			}	
		}		
		if($lo_id_cha_cu==$lo_id_cha)
		{
			//kiem tra xem la keo tu tren xuong hay keo tu duoi len
			$socuoi=$this->parseInt(substr($loid, $this->lastIndexOf($loid,'.')));
			$this->same_parent($elementId, $destPosition, $lo_id_cha, $lo_id_cu, $lo_id_moi, $programid);
		}
		else
		{
			$this->different_parent($elementId, $destPosition, $lo_id_cha, $lo_id_cu, $lo_id_moi, $programid);
			
		}
		return $str;				
 	}
	public function same_parent($elementId, $destPosition, $lo_id_cha, $lo_id_cu, $lo_id_moi, $programid)
	{
		//đẩy những thằng dưới LO mới kéo vào xuống => tăng LO-ID của nó lên ví dụ 5.1.2 se thanh 5.1.3 để nhuong vi trí 5.1.2 lại cho thằng mới kéo vào	
		//duyet tat ca cac LO khác cùng cấp, nếu số cuối của các LO này lớn hơn số cuối của thằng bị xóa thì đôn nó lên
		$this->capnhat_id_node_con2('999', $lo_id_cu, $programid);
		
		$sql="SELECT * FROM `mdl_learning_outcome` WHERE program_id=".$programid." and parent_lo_id='".$lo_id_cha."'  and lo_id !='".$lo_id_cu."'";
		$row = NULL;
		$arr=array();
		$arr_con=array();
		if ($result = $this->db->query($sql))
		{
			
			$index=$destPosition;
			while ($row = $this->db->fetchObject($result))
			{
				$loid=$row->lo_id;
				$sodausua=substr($loid, 0, $this->lastIndexOf($loid,'.'));
				$socuoisua=$this->parseInt(substr($loid, $this->lastIndexOf($loid,'.')));
				//kiem tra neu lo_id cua những thằng còn lại trong node mới kéo vào mà lớn hơn hoac bằng node mới kéo vào thì cap nhật tang lo_id len
				if($socuoisua == $destPosition || $socuoisua > $destPosition)
				{
					$index++;
					$socuoimoi=$index;
					if($sodausua=="")
					{
						$loid_moi=$socuoimoi;
					}
					else
					{
						$loid_moi=$sodausua.'.'.$socuoimoi;
					}
					$sql_update_lo= "update mdl_learning_outcome set lo_id='".$loid_moi."' where id=".$row->id;
					$this->db->query($sql_update_lo);
					
					$this->capnhat_id_node_con2($loid_moi, $loid, $programid);
					
				}
				else
				{
					
				}
				
			}
		}

		//sau khi tao duoc lo_id moi cho node con thi cap nhat lai parent_lo_id cua no va lo_id cua no
		$sql_update_lo_id = "update mdl_learning_outcome set lo_id='".$lo_id_moi."', parent_lo_id='".$lo_id_cha."' where id='".$elementId."' and program_id='".$programid."' ";
		$this->db->query($sql_update_lo_id);
		$this->capnhat_id_node_con2($lo_id_moi, '999', $programid);

		//cap nhat lai cac node cung cap cua thằng bị kéo đi
		//vi du thằng 4.2 bi keo qua 5 thì những thằng 4.3, 4.4 se duoc đôn lên,
		//$this->update_loid_after_delete($lo_id_cu, $lo_id_cha, $programid);
		
		//$out = '({"oldElementId":"'.$lo_id_moi.'", "elementId":"'. $lo_id_moi .'"})';
	}
	public function different_parent($elementId, $destPosition, $lo_id_cha, $lo_id_cu, $lo_id_moi, $programid)
	{
		//đẩy những thằng dưới LO mới kéo vào xuống => tăng LO-ID của nó lên ví dụ 5.1.2 se thanh 5.1.3 để nhuong vi trí 5.1.2 lại cho thằng mới kéo vào	
		//duyet tat ca cac LO khác cùng cấp, nếu số cuối của các LO này lớn hơn số cuối của thằng bị xóa thì đôn nó lên
		$sql="SELECT * FROM `mdl_learning_outcome` WHERE program_id=".$programid." and parent_lo_id='".$lo_id_cha."' order by lo_id desc";
		$row = NULL;
		$str= "";
		if ($result = $this->db->query($sql))
		{
			while ($row = $this->db->fetchObject($result))
			{
				$loid=$row->lo_id;
				$sodausua=substr($loid, 0, $this->lastIndexOf($loid,'.'));
				$socuoisua=$this->parseInt(substr($loid, $this->lastIndexOf($loid,'.')));
				//kiem tra neu lo_id cua những thằng còn lại trong node mới kéo vào mà lớn hơn hoac bằng node mới kéo vào thì cap nhật tang lo_id len
				if($socuoisua == $destPosition || $socuoisua > $destPosition)
				{
					$socuoimoi=$socuoisua+1;
					if($sodausua=="")
					{
						$loid_moi=$socuoimoi;
					}
					else
					{
						$loid_moi=$sodausua.'.'.$socuoimoi;
					}
					$sql_update_lo= "update mdl_learning_outcome set lo_id='".$loid_moi."' where id=".$row->id;
					$this->db->query($sql_update_lo);	 
					
					$this->capnhat_id_node_con($loid_moi, $loid, $programid);
				}
			}
		}
		//sau khi tao duoc lo_id moi cho node con thi cap nhat lai parent_lo_id cua no va lo_id cua no
		$sql_update_lo_id = "update mdl_learning_outcome set lo_id='".$lo_id_moi."', parent_lo_id='".$lo_id_cha."' where id='".$elementId."' and program_id='".$programid."' ";
		$this->db->query($sql_update_lo_id);
		echo $sql_update_lo_id;
		$this->capnhat_id_node_con($lo_id_moi, $lo_id_cu, $programid);
		//$out = '({"oldElementId":"'.$lo_id_moi.'", "elementId":"'. $lo_id_moi .'"})';
		
	}
	public function capnhat_id_node_con($loid_chamoi, $loid_chacu, $program_id)
	{
		//cap nhat node cha trước
		$sql_cap_nhat_cha = "update mdl_learning_outcome set parent_lo_id='".$loid_chamoi."' where parent_lo_id='".$loid_chacu."' and status>0 and program_id='".$program_id."' ";
		echo $sql_cap_nhat_cha.'; ';
		$this->db->query($sql_cap_nhat_cha);
		//giờ tới lượt cập nhật lo_id của node con theo node cha da thay doi
		$sql_duyet_lo_con = "select * from mdl_learning_outcome where parent_lo_id='".$loid_chamoi."' and program_id='".$program_id."' ";
		$row = NULL;
		if ($result = $this->db->query($sql_duyet_lo_con))
		{
			while ($row = $this->db->fetchObject($result))
			{
				if($row->lo_id!='')
				{
					$lo_id=$row->lo_id;
					$socuoisua=$this->parseInt(substr($lo_id, $this->lastIndexOf($lo_id,'.')));
					$lo_id_moi= $loid_chamoi.'.'.$socuoisua;
					$sql_cap_nhat_con = "update mdl_learning_outcome set lo_id='".$lo_id_moi."' where id='".$row->id."'";
						$this->db->query($sql_cap_nhat_con);
					$this->capnhat_id_node_con($lo_id_moi, $lo_id,$program_id);
				}	
			}
		}
	}
	public function getRootId(){
		return 0;
	}
 	
 }
 ?>